#ifndef _XBOOK_THREAD_H
#define _XBOOK_THREAD_H

#include <xbook/list.h>
#include <xbook/waitqueue.h>
#include <types.h>
#include <stdint.h>

/* thread state */
typedef enum {
    THREAD_READY = 0,         /* 线程处于就绪状态 */
    THREAD_RUNNING,           /* 线程正在运行中 */
    THREAD_BLOCKED,           /* 线程由于某种原因被阻塞 */
    THREAD_WAITING,           /* 线程处于等待子线程状态 */
    THREAD_STOPPED,           /* 线程处于停止运行状态 */
    THREAD_HANGING,           /* 线程处于挂起，等待父线程来回收  */
    THREAD_ZOMBIE,            /* 线程处于僵尸状态，父线程没有等待它 */
} thread_state_t;

#define MAX_THREAD_NAMELEN 32

/* 栈魔数，用于检测内核栈是否向下越界 */
#define THREAD_STACK_MAGIC 0X19980325

/* 栈中保存的最大参数个数 */
#define MAX_STACK_ARGC 16

/* 内核栈大小为8kb */
#define THREAD_KSTACK_SIZE    8192

#define THREAD_MIN_TIMESLICE  1
#define THREAD_MAX_TIMESLICE  100

/* 最多支持多少线程 */
#define NR_THREADS  64

/* 线程的标志 */
enum thread_flags {
    THREAD_FLAG_ALLOCED             = (1 << 0),     /* 分配状态 */
};

typedef struct priority_queue {
    list_t list;            /* 线程链表 */
    unsigned long length;   /* 队列长度 */
    unsigned int priority;  /* 优先级 */
} priority_queue_t;

typedef struct {
    unsigned char *kstack;              /* kernel stack, must be first member */
    thread_state_t state;               /* 线程的状态 */
    pid_t pid;                          /* 自己的线程id */
    pid_t parent_pid;                   /* 父线程id */
    pid_t tgid;                         /* 线程组id：线程属于哪个线程，和pid一样，就说明是主线程，不然就是子线程 */
    unsigned long flags;                /* 标志 */
    unsigned long priority;             /* 线程所在的优先级队列 */
    unsigned long ticks;                /* 运行的ticks，当前剩余的timeslice */
    unsigned long timeslice;            /* 时间片，可以动态调整 */
    unsigned long elapsed_ticks;        /* 线程执行总共占用的时间片数 */
    int exit_status;                    /* 退出时的状态 */
    char name[MAX_THREAD_NAMELEN];      /* 线程的名字 */
    list_t list;                        /* 处于所在队列的链表 */
    list_t global_list;                 /* 全局线程队列，用来查找所有存在的线程 */
    priority_queue_t *prio_queue;       /* 所在的优先级队列 */
    unsigned int stack_magic;           /* 线程的魔数 */
} thread_t;

extern thread_t *thread_current;   /* 当前线程指针 */
extern list_t thread_global_list;

#define current_thread    thread_current

#define set_current_state(stat) \
        current_thread->state = (stat)

void init_threads();

void thread_init(thread_t *thread, char *name, int priority);
void thread_free(thread_t *thread);

void dump_thread(thread_t *thread);

thread_t *kthread_start(char *name, int priority, thread_func_t *func, void *arg);
void kthread_exit(int status);

thread_t *find_thread_by_pid(pid_t pid);

void thread_global_list_add(thread_t *thread);
void thread_activate(thread_t *thread);
void thread_block(thread_state_t state);
void thread_block_ex(thread_state_t state, unsigned long flags);
void thread_unblock(thread_t *thread);
void thread_yeild();
void thread_set_timeslice(thread_t *thread, uint32_t timeslice);

#define thread_sleep() thread_block(THREAD_BLOCKED) 

static inline void thread_wakeup(thread_t *thread)
{
    if ((thread->state == THREAD_BLOCKED) || 
        (thread->state == THREAD_WAITING) ||
        (thread->state == THREAD_STOPPED)) {    
        thread_unblock(thread);
    }
}

void print_thread();

/**
 * breif: switch thread from prev to next
 * @Need platform support
 */
void thread_switch_to(thread_t *prev, thread_t *next);

/**
 * breif: make a thread execute env
 * @Need platform support
 */
void thread_make_stack(thread_t *thread, thread_func_t *function, void *arg);


void init_user();

#endif   /* _XBOOK_THREAD_H */
